package com.alit.ibot.robot.wechat.util;

import java.io.StringWriter;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.alit.ibot.robot.wechat.data.WechatMessageType;

/**
 * @author litong
 * @date 2019年5月31日_下午8:28:12
 * @version 1.0
 * @desc
 */
public class WechatXMLUtil {
  private static DocumentBuilder builer = null;
  private static Transformer transformer = null;
  static {
    initDocumentBuilder();
    initTransformer();
  }

  private static void initDocumentBuilder() {
    TransformerFactory fransformerFactory = TransformerFactory.newInstance();
    try {
      transformer = fransformerFactory.newTransformer();
    } catch (TransformerConfigurationException e) {
      e.printStackTrace();
    }
  }

  private static void initTransformer() {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

    documentBuilderFactory.setIgnoringElementContentWhitespace(true);
    try {
      builer = documentBuilderFactory.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    }

  }

  /**
   * 生成微信文本消息返回 标签 ToUserName,FromUserName,CreateTime,MsgType,Content
   * 
   * @param requestMap
   * @param content
   * @return
   */
  public static String toWechatTextXML(Map<String, String> requestMap, String content) {
    Document dom = initToUserNameAndFromUserNameAndCreateTimeAndMsgType(requestMap, WechatMessageType.text);

    Element ele = dom.createElement("Content");
    CDATASection cDATASection = dom.createCDATASection(content); // 设置新内容
    ele.appendChild(cDATASection);
    Element rootElement = dom.getDocumentElement();
    rootElement.appendChild(ele);

    return domToString(dom);
  }

  /**
   * dom转为xml格式
   * 
   * @param dom
   * @return
   */
  public static String domToString(Document dom) {
    StringWriter stringWriter = new StringWriter();
    try {
      transformer.transform(new DOMSource(dom), new StreamResult(stringWriter));
    } catch (TransformerException e) {
      e.printStackTrace();
    } finally {
    }
    return stringWriter.toString();
  }

  /**
   * 构建基本数据
   * 
   * @param requestMap
   * @param type
   * @return
   */
  public static Document initToUserNameAndFromUserNameAndCreateTimeAndMsgType(Map<String, String> requestMap,
      String type) {
    Document dom = builer.newDocument();
    Element rootEle = dom.createElement("xml");
    dom.appendChild(rootEle);
    Element ele = null;
    CDATASection cDATASection = null;

    ele = dom.createElement("ToUserName");
    cDATASection = dom.createCDATASection((String) requestMap.get("FromUserName"));
    ele.appendChild(cDATASection);
    rootEle.appendChild(ele);

    ele = dom.createElement("FromUserName");
    cDATASection = dom.createCDATASection((String) requestMap.get("ToUserName"));
    ele.appendChild(cDATASection);
    rootEle.appendChild(ele);

    ele = dom.createElement("CreateTime");
    ele.setTextContent((String) requestMap.get("CreateTime"));
    rootEle.appendChild(ele);

    ele = dom.createElement("MsgType");
    cDATASection = dom.createCDATASection(type);
    ele.appendChild(cDATASection);
    rootEle.appendChild(ele);
    return dom;
  }

  /**
   * 生成微信图片消息
   * 
   * @param requestMap
   * @param mediaId
   * @return
   */
  public static String toWechatImageXML(Map<String, String> requestMap, String mediaId) {
    Document dom = initToUserNameAndFromUserNameAndCreateTimeAndMsgType(requestMap, WechatMessageType.image);
    Element rootElement = dom.getDocumentElement();
    Element ele = dom.createElement("Image");

    Element medaiId = dom.createElement("MediaId");
    CDATASection cDATASection = dom.createCDATASection(mediaId); // 设置新内容
    medaiId.appendChild(cDATASection);

    ele.appendChild(medaiId);
    rootElement.appendChild(ele);

    return domToString(dom);
  }

  /**
   * 生成微信图文消息
   * 
   * @param requestMap
   * @param count
   * @param content
   */
  public static String toWechatImagetxtXML(Map<String, String> requestMap, String count, String xml) {
    Document dom = initToUserNameAndFromUserNameAndCreateTimeAndMsgType(requestMap, WechatMessageType.news);
    Element rootElement = dom.getDocumentElement();
    Element ele = dom.createElement("ArticleCount");
    CDATASection cDATASection = dom.createCDATASection(count);
    ele.appendChild(cDATASection);
    rootElement.appendChild(ele);
    Document document = DOMXMLUtil.parseXMLToDocument(xml);
    Element articles = document.getDocumentElement();
    // rootElement.appendChild(articles); //org.w3c.dom.DOMException:
    // WRONG_DOCUMENT_ERR: 使用节点的文档与创建节点的文档不相同。
    String tagName = articles.getTagName();
    NodeList nodeList = articles.getChildNodes();

    Element newArticles = dom.createElement(tagName);
    rootElement.appendChild(newArticles);

    for (int i = 0; i < nodeList.getLength(); i++) {
      Node item = nodeList.item(i);
      Element newItem = dom.createElement(item.getNodeName());
      newArticles.appendChild(newItem); // 添加一个Item
      NodeList childNodes = item.getChildNodes();
      for (int j = 0; j < childNodes.getLength(); j++) {
        Node n = childNodes.item(j);
        Element newElmment = dom.createElement(n.getNodeName());
        CDATASection newCDATA = dom.createCDATASection(n.getTextContent());
        newElmment.appendChild(newCDATA);
        newItem.appendChild(newElmment); // 添加 Title,Description,Url
      }
    }
    return domToString(dom);
  }

  /**
   * 生成微信音乐消息
   */
  public static String toWechatMusicXML(Map<String, String> requestMap, String title, String desc, String url,
      String mediaId) {
    Document dom = initToUserNameAndFromUserNameAndCreateTimeAndMsgType(requestMap, WechatMessageType.music);
    Element rootElement = dom.getDocumentElement();
    Element music = dom.createElement("Music");
    rootElement.appendChild(music);

    Element e = dom.createElement("Title");
    CDATASection c = dom.createCDATASection(title);
    e.appendChild(c);
    music.appendChild(e);

    e = dom.createElement("Description");
    c = dom.createCDATASection(desc);
    e.appendChild(c);
    music.appendChild(e);

    e = dom.createElement("MusicUrl");
    c = dom.createCDATASection(url);
    e.appendChild(c);
    music.appendChild(e);

    e = dom.createElement("HQMusicUrl");
    c = dom.createCDATASection(url);
    e.appendChild(c);
    music.appendChild(e);

    e = dom.createElement("ThumbMediaId");
    c = dom.createCDATASection(mediaId);
    e.appendChild(c);
    music.appendChild(e);
    return domToString(dom);
  }

  /**
   * 生成视频消息
   */
  public static String toWechatMusicXML(Map<String, String> requestMap, String title, String desc, String mediaId) {
    Document dom = initToUserNameAndFromUserNameAndCreateTimeAndMsgType(requestMap, WechatMessageType.video);
    Element rootElement = dom.getDocumentElement();
    Element music = dom.createElement("Video");
    rootElement.appendChild(music);

    Element e = dom.createElement("MediaId");
    CDATASection c = dom.createCDATASection(mediaId);
    e.appendChild(c);
    music.appendChild(e);
    
    e = dom.createElement("Title");
    c = dom.createCDATASection(title);
    e.appendChild(c);
    music.appendChild(e);

    e = dom.createElement("Description");
    c = dom.createCDATASection(desc);
    e.appendChild(c);
    music.appendChild(e);

    return domToString(dom);
  }
}
